#pragma once

#include "geometry.h"

class Beachline
{
public:
	Beachline(const Site& site) : site_(site){}

	int isSitePoint() const { return site_.isPoint_; }
	Site getSite() const { return site_; }
	static Beachline *New(const Site& site);

	/**
	* @fn double evaluateXAt(double y, double directrix) const
	* @brief Given of directrix, evaluate x-coordinate of the point on the
	* parabola with the given y-coordinate
	* @param y Y-coordinate for the point to be evaluated.
	* @param directrix Directrix of the Parabola.
	*/
	virtual double evaluateXAt(double y, double directrix) const = 0;

	/**
	* @fn void intersect(const Parabola& peer, double directrix,
	double *y1, double *y2) const
	* @brief calculate the intersection of two parabola under a given
	* directrix.
	* @param peer The parabola to intersect with this parabola.
	* @param directrix The directrix for both parabola.
	* @param y1 Output of the higher intersection.
	* @param y2 Output of the lower intersection.
	*/
	virtual bool intersect(const Beachline *peer, double directrix,
		double& y1, double& y2) const = 0;

	/**
	* @fn void intersect(const Parabola& peer, double directrix,
	Point *p1, Point *p2) const
	* @brief calculate the intersection of two parabola under a given
	* directrix.
	* @param peer The parabola to intersect with this parabola.
	* @param directrix The directrix for both parabola.
	* @param p1 Output of the higher intersection.
	* @param p2 Output of the lower intersection.
	*/
	virtual bool intersect(const Beachline *peer, double directrix,
		Vector& p1, Vector& p2) const = 0;

	Vector *getDivision(double low, double high, double time, int& size) const;

protected:
	Site site_;
};
/**
* @class Parabola
* @brief 2-D parabola with a directrix parallel to y-axis.
*/
class Parabola : public Beachline
{
public:
	/**
	* @name constructors
	* @brief Constructors for Parabola
	*/
	/*@{*/
	/** Default constructor with focus at (0, 0) */
	//Parabola() : Beachline(1) {}
	/** Constructor with focus at fcs */
	Parabola(const Site& p) : Beachline(p) {}
	/*@}*/

	Vector getFocus() const { return site_.p0_; }
	double evaluateXAt(double y, double directrix) const;

	bool intersect(const Beachline *peer, double directrix,
		double& y1, double& y2) const;

	bool intersect(const Beachline *peer, double directrix,
		Vector& p1, Vector& p2) const;

};

class Polyline : public Beachline
{
public:
	//Polyline() : Beachline(0) {}
	Polyline(const Site& p);

	bool isVertical() const { return equalDouble(site_.p0_.x, site_.p1_.x); }
	Vector getStartPoint() const { return site_.p0_; }
	Vector getEndPoint() const { return site_.p1_; }
	double getAboveTang() const { return above_tang; }
	double getBelowTang() const { return below_tang; }

	double evaluateXAt(double y, double directrix) const;

	bool intersect(const Beachline *peer, double directrix,
		double& y1, double& y2) const;

	bool intersect(const Beachline *peer, double directrix,
		Vector& p1, Vector& p2) const;

private:
	double above_tang;
	double below_tang;
};

class ParaEdge
{
public:
	ParaEdge(const Vector& f, const Vector& p0, const Vector& p1);

	Vector *getDivision(const Vector& p0, const Vector& p1, int& size);

private:
	Vector focus_;
	Vector dest_;
	double length_;
};

